package _binary_tree

import common.TreeNode
import org.junit.Assert
import org.junit.Test

/**
 * https://leetcode.cn/problems/evaluate-boolean-binary-tree/description
 *
 * ```
 * 2331. 计算布尔二叉树的值
 *
 * 给你一棵 完整二叉树 的根，这棵树有以下特征：
 *
 * 叶子节点 要么值为 0 要么值为 1 ，其中 0 表示 False ，1 表示 True 。
 * 非叶子节点 要么值为 2 要么值为 3 ，其中 2 表示逻辑或 OR ，3 表示逻辑与 AND 。
 * 计算 一个节点的值方式如下：
 * 如果节点是个叶子节点，那么节点的 值 为它本身，即 True 或者 False 。
 * 否则，计算 两个孩子的节点值，然后将该节点的运算符对两个孩子值进行 运算 。
 * 返回根节点 root 的布尔运算值。
 * 完整二叉树 是每个节点有 0 个或者 2 个孩子的二叉树。
 * 叶子节点 是没有孩子的节点。
 *
 * 示例 1：
 * 输入：root = [2,1,3,null,null,0,1]
 * 输出：true
 * 解释：上图展示了计算过程。
 * AND 与运算节点的值为 False AND True = False 。
 * OR 运算节点的值为 True OR False = True 。
 * 根节点的值为 True ，所以我们返回 true 。
 *
 * 示例 2：
 * 输入：root = [0]
 * 输出：false
 * 解释：根节点是叶子节点，且值为 false，所以我们返回 false 。
 *
 * 提示：
 * 树中节点数目在 [1, 1000] 之间。
 * 0 <= Node.val <= 3
 * 每个节点的孩子数为 0 或 2 。
 * 叶子节点的值为 0 或 1 。
 * 非叶子节点的值为 2 或 3 。
 * ```
 */
class leetcode_2331 {
    @Test
    fun test_2() {
        val root = TreeNode(0)
        val actual = evaluateTree(root)
        val expected = false
        Assert.assertEquals(expected, actual)
    }

    fun evaluateTree(root: TreeNode?): Boolean {
        /**
        题型：二叉树的后序遍历 + 分治法

        思路：
        根据叶子和非叶子节点，返回指定的值
         */

        // 1 确定函数参数以及返回值
        // 2 确定终止条件
        if(null == root){
            // 返回true/false都可以
            return false
        }

        // 3 确定单层递归的处理逻辑：后序遍历
        // 左
        val left = evaluateTree(root.left)

        // 右
        val right = evaluateTree(root.right)

        // 中
        // 叶子节点：直接返回true/false
        if(root.`val` == 0){
            return false
        }

        if(root.`val` == 1){
            return true
        }

        // 非叶子节点：计算
        if(root.`val` == 2){
            // TODO:OR 或 // 都可以
            return left or right
        }
        if(root.`val` == 3){
            // TODO:AND 或 && 都可以
            return left and right
        }
        // 返回true/false都可以
        return false
    }
    private fun evaluateTree2(root: TreeNode?): Boolean {
        /**
        题型：二叉树的后序遍历 + 分治法

        思路：
        根据叶子和非叶子节点，返回指定的值
         */
        // 1 确定函数的参数以及返回值
        // 2 确定终止条件
        if (null == root) {
            return false
        }
        // 3 确定单次递归的处理逻辑：  后序遍历
        // 非叶子节点
        if (root.left != null && root.right != null) {
            // 左
            val left = evaluateTree(root.left)

            // 右
            val right = evaluateTree(root.right)

            // 中
            if (root.`val` == 3) { // 3 => AND
                // TODO:AND 或 && 都可以
                return left && right
            } else { // 2 => OR
                // TODO:AND 或 && 都可以
                return left || right
            }
        } else {
            // 叶子节点 要么值为 0 要么值为 1 ，其中 0 表示 False ，1 表示 True 。
            return root.`val` == 1
        }
    }
}